import yaml

class Skill:

    HYPER_FLAG = "U"

    def __init__(self, name, skills_config):
        self.is_hyper = self._is_hyper(name)
        self.category = self._get_category(name, skills_config)
        self.name = self._handle_name(name, self.is_hyper, skills_config)
        self.bindable = self._is_bindable(name, skills_config)
       
    def __str__(self):
        return f'{self.name}' + ('(Bindable)' if self.bindable else '')
    
    def _get_category(self, name, skills_config):
        cate = []
        lower_name = self._get_lower_name(name)
        if lower_name in skills_config and 'category' in skills_config[lower_name]:
            cate =  skills_config[lower_name]['category']
            if not isinstance(cate, list):
                cate = [cate]
        return cate

    def _is_bindable(self, name, skills_config):
        lower_name = self._get_lower_name(name)
        if lower_name in skills_config and 'bind' in skills_config[lower_name]:
            return skills_config[lower_name]['bind'] == '1'
        return False

    def _is_hyper(self, name):
        return name.startswith(Skill.HYPER_FLAG)

    def _get_lower_name(self, name):
        if name.startswith(Skill.HYPER_FLAG):
            return name[1:]
        return name

    def _handle_name(self, name, is_hyper, skills_config):
        result = name
        lower_name = self._get_lower_name(name)
        if is_hyper:
            if lower_name not in skills_config or 'hyper_name' not in skills_config[lower_name]:
                result = '高级' + lower_name
            else:
                result = skills_config[lower_name]['hyper_name']
        else:
            result = lower_name
        return result
    
    def __str__(self) -> str:
        return f'{self.name}' + ('(Bindable)' if self.bindable else '')
    
    def __dict__(self):
        return {'name': self.name, 'bindable': self.bindable, 'hyper': self._is_hyper}

class Animal:

    NECESSARY_FLAG = "ND"

    def __init__(self, name, skills, level, skills_config):
        self.name = name
        # 去掉skills数组中元素末尾的ND，并不是每个技能都有ND
        self.skills = [*skills]
        self.necessary_skills = []
        for i in range(len(skills)):
            if self.skills[i].endswith(Animal.NECESSARY_FLAG):
                self.necessary_skills.append(self.skills[i])
                self.skills[i] = self.skills[i].replace(Animal.NECESSARY_FLAG, '')
        self.skills = [Skill(skill, skills_config) for skill in self.skills]
        self.necessary_skills = [Skill(skill, skills_config) for skill in self.necessary_skills]
        self.level = level

    def __dict__(self):
        return {'name': self.name, 'skills': [skill.__dict__() for skill in self.skills], 'necessary_skills': [skill.__dict__() for skill in self.necessary_skills], 'level': self.level}

    def __str__(self) -> str:
        # 以更友好的方式输出，不同属性不同行
        return f'Name: {self.name}\nSkills: {list(map(lambda s: str(s), self.skills))}\nNecessary Skills: {list(map(lambda s: str(s), self.necessary_skills))}\nLevel: {self.level}'

def load():
    # 从animal.yaml文件中读取数据
    with open('animal.yaml', 'r', encoding="utf-8") as f:
        data = yaml.load(f, Loader=yaml.FullLoader)
        animal_configs =  dict()
        skill_configs = dict()
        for skill in data['skills']:
            skill_configs[skill['name']] = skill

        for animal in data['animals']:
            animal_configs[animal['name']] = Animal(animal['name'], animal['skills'], animal['level'], skill_configs)
        return animal_configs, skill_configs


animal_configs, skill_configs = load()

skills = [*map(lambda s: Skill(s, skill_configs), skill_configs.keys()), *map(lambda s: Skill(f'U{s}', skill_configs), skill_configs.keys())]

category_skill_map = dict()

for skill in skills:
    category = skill.category
    for c in category:
        if c not in category_skill_map:
            category_skill_map[c] = []
        category_skill_map[c].append(Skill(skill.name, skill_configs))

